using System.Xml;

namespace ServiceModel.Syndication.LEAP2A {
    /// <summary>
    /// Base class for personal and organisational data
    /// </summary>
    public class LeapDataItem {
        /// <summary>
        /// Gets or sets the field type, standard value are available as static mebmers of LeapPersonalFieldTypes.
        /// More details are available at http://wiki.cetis.ac.uk/2009-03/LEAP2A_personal_data
        /// </summary>
        /// <value>The field.</value>
        public string Field {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the label for this field, this is normally the label used in the UI of the portfolio.
        /// </summary>
        /// <value>The label.</value>
        public string Label {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the value of this field.
        /// </summary>
        /// <value>The value.</value>
        public string Value {
            get;
            set;
        }

        /// <summary>
        /// Tries the parse person or organisation data from an element,
        /// return LeapDataItem, LeapServiceData or LeapCountryData based on the attributes present.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>
        /// LeapDataItem, LeapServiceData, LeapCountryData or null
        /// </returns>
        public static LeapDataItem TryParseDataItem(XmlReader reader) {
            LeapDataItem data;

            switch (reader.GetAttribute("field", reader.NamespaceURI)) {
                case "id":
                    data = new LeapServiceData();
                    break;
                case "country":
                    data = new LeapCountryData();
                    break;
                default:
                    data = new LeapDataItem();
                    break;
            }
            
            data.TryParseElement(reader);

            return data;
        }

        protected virtual void WriteAttributes(XmlWriter writer, LeapFeed feed) {
            writer.WriteAttributeString(
                feed.LeapPredicatesNamespacePrefix,
                "field",
                feed.LeapPredicatesNamespace,
                Field);

            if (!string.IsNullOrEmpty(Label)) {
                writer.WriteAttributeString(
                    feed.LeapPredicatesNamespacePrefix,
                    "label",
                    feed.LeapPredicatesNamespace,
                    Label);
            }
        }

        protected virtual bool TryParseElement(XmlReader reader) {
            if (reader.LocalName == "persondata" || reader.LocalName == "orgdata") {
                this.Field = reader.GetAttribute(reader.Prefix + ":field");
                this.Label = reader.GetAttribute(reader.Prefix + ":label");

                this.Value = LeapItem.GetTextContent(reader);

                return true;
            }

            return false;
        }

        /// <summary>
        /// Writes the personal or organisation data to a LEAP2A feed.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <param name="tag">The tag.</param>
        public void WriteTo(XmlWriter writer, string tag, LeapFeed feed) {
            writer.WriteStartElement(
                        feed.LeapPredicatesNamespacePrefix,
                        tag, feed.LeapPredicatesNamespace);

            WriteAttributes(writer, feed);

            if (Value != null) {
                writer.WriteValue(Value);
            }

            writer.WriteEndElement();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LeapDataItem"/> class.
        /// </summary>
        public LeapDataItem() {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LeapDataItem"/> class.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        public LeapDataItem(string field, string value) {
            this.Field = field;
            this.Value = value;
        }
    }
}
